package com.echat.serviceapigateway.security.tool;

import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by xiaoyu on 2015/4/4.
 */
public class StringUtils {

    private static DecimalFormat decimalFormat = new DecimalFormat("0.00");

    private static final String zero = "0";

    private static final String one = "1";

    public static final String emptyStr = "";

    public static final String keySplit = ",";//分隔符

    //本机访问服务时,会获取到ipv6的地址
    private static final String LOCAL_IPV6 = "0:0:0:0:0:0:0:1";

    /**
     * 判断IP格式和范围
     */
    public static final String IP_REXP = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";

    public static boolean isNotEmpty(String str) {
        return str != null && !emptyStr.equals(str);
    }

    public static boolean isEmpty(String str) {
        return str == null || emptyStr.equals(str);
    }

    /**
     * @param st
     * @return 返回escape过后的字符串
     */
    public static String escapeAttributeEntities(String st) {
        if (isEmpty(st)) {
            return st;
        }
        //StringBuffer 是同步和线程安全的，效率低，StringBuilder是不同步的，效率高
        StringBuilder buff = new StringBuilder();
        char block[] = st.toCharArray();
        String stEntity = null;
        int i = 0;
        int last = 0;
        for (; i < block.length; i++) {

            //使用空格替代非法字符.
            if (!isXMLCharacter(block[i])) {
                block[i] = (char) 0x20;
                continue;
            }

            switch (block[i]) {
                case 60: // '<'
                    stEntity = "&lt;";
                    break;

                /*case 62: // '>'
                    stEntity = "&gt;";
                    break;

                case 39: // '\''
                    stEntity = "&apos;";
                    break;

                case 34: // '"'
                    stEntity = "&quot;";
                    break;

                case 38: // '&'
                    stEntity = "&amp;";
                    break;*/
            }
            if (stEntity != null) {
                buff.append(block, last, i - last);
                buff.append(stEntity);
                stEntity = null;
                last = i + 1;
            }
        }

        if (last < block.length) {
            buff.append(block, last, i - last);
        }
        return buff.toString();
    }

    /**
     * @param st String
     * @return String
     */
    public static String escapeElementEntities(String st) {
        if (st == null) {
            return null;
        }
        //StringBuffer 是同步和线程安全的，效率低，StringBuilder是不同步的，效率高
        StringBuilder buff = new StringBuilder();
        char block[] = st.toCharArray();
        String stEntity = null;
        int i = 0;
        int last = 0;
        for (; i < block.length; i++) {

            //使用空格替代非法字符.
            if (!isXMLCharacter(block[i])) {
                block[i] = (char) 0x20;
                continue;
            }

            switch (block[i]) {
                case 60: // '<'
                    stEntity = "&lt;";
                    break;

                case 62: // '>'
                    stEntity = "&gt;";
                    break;

                case 38: // '&'
                    stEntity = "&amp;";
                    break;
            }
            if (stEntity != null) {
                buff.append(block, last, i - last);
                buff.append(stEntity);
                stEntity = null;
                last = i + 1;
            }
        }

        if (last < block.length) {
            buff.append(block, last, i - last);
        }
        return buff.toString();
    }

    private static boolean isXMLCharacter(int c) {
        if (c <= 0xD7FF) {
            if (c >= 0x20)
                return true;
            else
                return c == '\n' || c == '\r' || c == '\t';
        }
        return (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF);
    }

    /**
     * 首字母转大写
     *
     * @param str
     * @return
     */
    public static String firstToUpperCase(String str) {
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        return sb.toString();
    }

    public static String listToString(List list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        Object obj = null;
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            obj = list.get(i);
            if (i != list.size() - 1) {
                buffer.append(obj).append(keySplit);
            } else {
                buffer.append(obj);
            }
        }
        return buffer.toString();
    }

    public static String setToString(Set set) {
        if (set == null || set.size() == 0) {
            return null;
        }
        int i = 0;
        Object obj = null;
        StringBuffer buffer = new StringBuffer();
        Iterator it = set.iterator();
        while (it.hasNext()) {
            obj = it.next();
            if (i != set.size() - 1) {
                buffer.append(obj).append(keySplit);
            } else {
                buffer.append(obj);
            }
            i++;
        }
        return buffer.toString();
    }

    /**
     * 逗号分隔的字符串转list
     *
     * @param source
     * @return
     */
    public static List stringToList(String source) {
        if (isEmpty(source)) {
            return null;
        }
        String[] arr = split(source, keySplit.charAt(0));
        List list = Arrays.asList(arr);
        return new ArrayList(list);
    }

    /**
     * 逗号分隔的字符串转List 用于Like查询
     *
     * @param source
     * @return
     */
    public static List stringToListAsLike(String source) {
        if (isEmpty(source)) {
            return null;
        }
        String[] arr = split(source, keySplit.charAt(0));
        List res = new ArrayList();
        for (String str : arr) {
            res.add("%" + str + "%");
        }
        return res;
    }

    /**
     * 指定分隔符的字符串转list
     *
     * @param source
     * @param separator
     * @return
     */
    public static List stringToList(String source, String separator) {
        if (isEmpty(source) || isEmpty(separator)) {
            return null;
        }
        String[] arr = split(source, separator.charAt(0));
        List list = Arrays.asList(arr);
        return new ArrayList(list);
    }

    /**
     * 判断字符串是否相等
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean equals(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }

    /**
     * 判断字符串转字节是否相等
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean equals(String str1, byte str2) {
        return str1 != null ? Byte.valueOf(str1).byteValue() == str2 : false;
    }

    /**
     * 判断字符串转整形是否相等
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean equals(String str1, int str2) {
        return str1 != null ? Integer.valueOf(str1).intValue() == str2 : false;
    }

    /**
     * 判断字符串转long是否相等
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean equals(String str1, long str2) {
        return str1 != null ? Long.valueOf(str1).longValue() == str2 : false;
    }

    /**
     * 判断是否为数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        if (isEmpty(str)) {
            return false;
        }
        int sz = str.length();
        for (int i = 0; i < sz; i++) {
            if (Character.isDigit(str.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否为数字，包含小数。注意有bug，如果str是以0开头的整数，也会认为是数字
     * by HeLL
     *
     * @param str
     * @return
     */
    public static boolean myIsNumeric(String str) {
        if (isEmpty(str)) {
            return false;
        }
        //匹配数字，包括小数和负数。现有BUG，0123可以匹配成数字，但0123.2不匹配
        return str.matches("^-?([1-9]{1}[0-9]*|[0]{1}){1}(\\.[0-9]+)?$");
    }

    /**
     * 匹配拆分此字符串
     *
     * @param str
     * @param separatorChar
     * @return
     */
    public static String[] split(String str, char separatorChar) {
        if (str == null) {
            return null;
        }
        int len = str.length();
        if (len == 0) {
            return new String[0];
        }
        List list = new ArrayList();
        int i = 0, start = 0;
        boolean match = false;
        boolean lastMatch = false;
        while (i < len) {
            if (str.charAt(i) == separatorChar) {
                if (match) {
                    list.add(str.substring(start, i));
                    match = false;
                    lastMatch = true;
                }
                start = ++i;
                continue;
            }
            lastMatch = false;
            match = true;
            i++;
        }
        if (match || lastMatch) {
            list.add(str.substring(start, i));
        }
        return (String[]) list.toArray(new String[list.size()]);
    }

    /**
     * 判断域名是否相等，支持多级域名
     *
     * @param domain
     * @param value
     * @return
     */
    public static boolean domainEqual(String domain, String value) {
        if (isEmpty(domain) || isEmpty(value)) {
            return false;
        }
        String[] array1 = split(domain, '.');
        String[] array2 = split(value, '.');
        if (array1.length == array2.length) {
            return equals(domain, value);
        } else {
            if (array1.length > array2.length) {
                int index = domain.indexOf(".");
                int beginIndex = value.startsWith(".") ? index : index + 1;
                String temp = domain.substring(beginIndex, domain.length());
                return equals(temp, value);
            } else {
                int index = value.indexOf(".");
                int beginIndex = domain.startsWith(".") ? index : index + 1;
                String temp = value.substring(beginIndex, value.length());
                return equals(domain, temp);
            }
        }
    }

    /**
     * dividend除以divisor保留两位小数
     *
     * @param dividend
     * @param divisor
     * @return
     */
    public static String divisionTwoDecimalPlaces(String dividend, String divisor) {
        if (isEmpty(dividend) || isEmpty(divisor)) {
            return null;
        }
        if (equals(dividend, zero)) {
            return zero;
        }
        if (equals(divisor, zero)) {
            return one;
        }
        double result = Double.valueOf(dividend) / Double.valueOf(divisor);
        return decimalFormat.format(result);
    }

    /**
     * 判断字符串数组是否包含字符串
     *
     * @param strArray
     * @param searchStr
     * @return
     */
    public static boolean contains(String[] strArray, String searchStr) {
        if (strArray == null || searchStr == null) {
            return false;
        }
        for (String s : strArray) {
            if (equals(s, searchStr)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 判断字符串1是否包含字符串2
     *
     * @param str
     * @param searchStr
     * @return
     */
    public static boolean contains(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.indexOf(searchStr) >= 0;
    }

    public static Map<String, String> getParamsMap(String queryString) {
        if (isEmpty(queryString)) {
            return null;
        }
        Map<String, String> map = new HashMap();
        String[] params = queryString.split("&");
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                String[] p = params[i].split("=");
                if (p.length == 2) {
                    map.put(p[0], p[1]);
                }
            }
        }
        return map;
    }

    /**
     * 判断str是否超过了maxSize，如果超过了就要进行截断
     *
     * @param str
     * @param maxSize
     * @return
     */
    public static boolean isToTruncation(String str, int maxSize) {
        if (isEmpty(str) || maxSize < 0) {
            return false;
        }
        return str.length() > maxSize;
    }

    /**
     * 返回截断后的字符串
     *
     * @param str     将要截断的字符串
     * @param maxSize 字符串的最大长度
     * @return
     */
    public static String truncation(String str, int maxSize) {
        if (isEmpty(str)) {
            return "";
        }
        return str.substring(0, maxSize);
    }

    /**
     * 如果小于maxSize则直接返回，否则返回截断后的字符串
     *
     * @param str     将要截断的字符串
     * @param maxSize 字符串的最大长度
     * @return
     */
    public static String truncationByInt(String str, int maxSize) {
        if (isEmpty(str)) {
            return "";
        }
        if (str.length() <= maxSize) {
            return str;
        } else {
            return str.substring(0, maxSize);
        }
    }


    /**
     * 判断字符串忽略大小写后是否相等
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean equalsIgnoreCase(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
    }

    /**
     * 获取jsonp格式返回值
     *
     * @param function
     * @param data
     * @return
     */
    public static String getJsonpResponse(String function, String data) {
        if (isEmpty(function) || isEmpty(data)) {
            return null;
        }
        return function + "(" + data + ")";
    }

    /**
     * unicode转换成字符串(不对外使用)
     *
     * @param str
     * @return
     */
    public static String unicodeToString(String str) {
        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            str = str.replace(matcher.group(1), ch + "");
        }
        return str;
    }

    /**
     * 将字符串中的 // -> \
     *
     * @param orgin
     * @return
     */
    public static String toSprit(String orgin) {
        String str = orgin.replace("\\", "/");
        return str;
    }

    public static Map<String, String> getFileContents(String dir) {
        HashMap<String, String> map = new HashMap<>();
        if (!dir.endsWith("/")) {
            dir += "/";
        }
        File file = new File(dir);
        if (file == null) {
            return null;
        }
        String[] fileName = file.list();
        if (fileName.length == 0) {
            return new HashMap<>();
        }
        for (String f : fileName) {
            map.put(f, readToString(dir + f));
        }

        return map;
    }

    public static String readToString(String fileName) {
        String encoding = "UTF-8";
        File file = new File(fileName);
        Long filelength = file.length();
        byte[] filecontent = new byte[filelength.intValue()];
        try {
            FileInputStream in = new FileInputStream(file);
            in.read(filecontent);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            return new String(filecontent, encoding);
        } catch (UnsupportedEncodingException e) {
            System.err.println("The OS does not support " + encoding);
            e.printStackTrace();
            return null;
        }
    }

    public static boolean checkIps(String ips) throws IllegalArgumentException {
        if(StringUtils.isEmpty(ips)){
            return true;
        }
        String[] addrs = ips.split(",");
        for (String addr : addrs) {
            if (addr == null || addr.length() < 7 || addr.length() > 15 || "".equals(addr)) {
                throw new IllegalArgumentException(addr);
            }
            Pattern pat = Pattern.compile(IP_REXP);
            Matcher mat = pat.matcher(addr);
            if (!mat.find() && !addr.equals(LOCAL_IPV6)) {
                throw new IllegalArgumentException(addr);
            }
        }
        return true;
    }

}
